/**
 * @file camera.c
 * @brief 摄像头模块
 *
 * @author 钟涛
 *
 * @date 2022-05-22
 *
 * @copyright 海南大学 - 追光者
 */

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"
#include "app_main.h"
#include <string.h>
#include "motor.h"

#define DBG_TAG "camera"
#define DBG_LVL DBG_ERROR
#include <rtdbg.h>

rt_device_t dev_uart3;
static rt_device_t dev_uart;

static rt_event_t event;

static const char cmd_camera_start = 0x0E;

struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */
static struct rt_semaphore rx_sem; /* 用于接收消息的信号量 */

/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    /* 串口接收到数据后产生中断，调用此回调函数，然后发送接收信号量 */
    rt_sem_release(&rx_sem);

    return RT_EOK;
}

static uint8_t packet[28];
static int packet_index;
static const uint8_t PACKET_HEADERS[] = { 0x55, 0xaa };

/**
 * @brief 读取数据包
 *
 * @param ch 每次收到的一个字节
 */
static void read_packet(uint8_t ch)
{
    packet[packet_index++] = ch;
    if (packet_index <= sizeof(PACKET_HEADERS))
    {
        /* 不符合帧头则归零 */
        if (ch != PACKET_HEADERS[packet_index - 1])
        {
            packet_index = 0;
        }
    }
    else if (packet_index == sizeof(packet))
    {
        /* 读到一整个数据包，校验帧尾和校验和等 */
        packet_index = 0;
        LOG_D("recv full packet", packet);
        uint16_t checksum = 0;
        for (int i = 6; i < sizeof(packet); i++)
        {
            checksum += packet[i];
        }
        if (checksum != packet[4] + (packet[5] << 8))
        {
            LOG_W("checksum error");
            return;
        }

        for (int i = 8; i < sizeof(packet); ++i)
        {
            switch (packet[i])
            {
            case 0x00:
                Stop();
                break;

            case 0x01:
                LOG_D("Forward");
                Forward();
                break;

            case 0x02:
                LOG_D("Backward");
                Backward();
                break;

            case 0x03:
                LOG_D("Rightward");
                Rightward();
                break;

            case 0x04:
                LOG_D("Leftward");
                Leftward();
                break;

//            case 0x0E:
//                rt_device_write(dev_uart3, 0, &cmd_camera_start, 1);
//                break;

            case 0x22:
                LOG_I("camera_uu");
                camera_uu();
                break;

            case 0x23:
                LOG_I("camera_dd");
                camera_dd();
                break;

            case 0x24:
                //camera_ud_middle();
                break;

            case 0x25:
                LOG_I("camera_ll");
                camera_ll();
                break;

            case 0x26:
                LOG_I("camera_rr");
                camera_rr();

                break;
            case 0x27:
                //camera_lr_middle();
                break;
            }
        }
    }
    LOG_D("recv ch: %02x, packet_index: %d", ch, packet_index);
}

static void remote_control_thread(void *params)
{
    char ch;
    while (1)
    {
        /* 从串口读取一个字节的数据，没有读取到则等待接收信号量 */
        while (rt_device_read(dev_uart, 0, &ch, 1) != 1)
        {
            /* 阻塞等待接收信号量，等到信号量后再次读取数据 */
            rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
        }
        // 处理ch...
        read_packet(ch);
    }
}

static int uart6_init(void)
{
    /* 初始化信号量 */
    rt_sem_init(&rx_sem, "rc", 0, RT_IPC_FLAG_FIFO);
    event = rt_event_create("event", RT_IPC_FLAG_PRIO);
    dev_uart = rt_device_find(UART6_DEV_NAME);
    config.baud_rate = BAUD_RATE_921600;        //修改波特率
    /* step3：控制串口设备。通过控制接口传入命令控制字，与控制参数 */
    rt_device_control(dev_uart, RT_DEVICE_CTRL_CONFIG, &config);
    rt_device_open(dev_uart, RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX);

    rt_thread_t thread = rt_thread_create("rc", remote_control_thread, NULL, 2048, PRIO_REMOTE_CONTROL, 10);
    rt_thread_startup(thread);
    rt_device_set_rx_indicate(dev_uart, uart_input);

    return 0;
}
INIT_PREV_EXPORT(uart6_init);
